home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / bsp / qvis3 / qvis3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-03  |  12.0 KB  |  596 lines

  1. // vis.c
  2.  
  3. #include "vis.h"
  4. #include "threads.h"
  5. #include "stdlib.h"
  6.  
  7. int            numportals;
  8. int            portalclusters;
  9.  
  10. char        inbase[32];
  11. char        outbase[32];
  12.  
  13. portal_t    *portals;
  14. leaf_t        *leafs;
  15.  
  16. int            c_portaltest, c_portalpass, c_portalcheck;
  17.  
  18. byte        *uncompressedvis;
  19.  
  20. byte    *vismap, *vismap_p, *vismap_end;    // past visfile
  21. int        originalvismapsize;
  22.  
  23. int        leafbytes;                // (portalclusters+63)>>3
  24. int        leaflongs;
  25.  
  26. int        portalbytes, portallongs;
  27.  
  28. qboolean        fastvis;
  29. qboolean        nosort;
  30.  
  31. int            testlevel = 2;
  32.  
  33. int        totalvis;
  34.  
  35. portal_t    *sorted_portals[MAX_MAP_PORTALS*2];
  36.  
  37.  
  38. //=============================================================================
  39.  
  40. void PlaneFromWinding (winding_t *w, plane_t *plane)
  41. {
  42.     vec3_t        v1, v2;
  43.  
  44. // calc plane
  45.     VectorSubtract (w->points[2], w->points[1], v1);
  46.     VectorSubtract (w->points[0], w->points[1], v2);
  47.     CrossProduct (v2, v1, plane->normal);
  48.     VectorNormalize (plane->normal, plane->normal);
  49.     plane->dist = DotProduct (w->points[0], plane->normal);
  50. }
  51.  
  52.  
  53. /*
  54. ==================
  55. NewWinding
  56. ==================
  57. */
  58. winding_t *NewWinding (int points)
  59. {
  60.     winding_t    *w;
  61.     int            size;
  62.     
  63.     if (points > MAX_POINTS_ON_WINDING)
  64.         Error ("NewWinding: %i points", points);
  65.     
  66.     size = (int)((winding_t *)0)->points[points];
  67.     w = malloc (size);
  68.     memset (w, 0, size);
  69.     
  70.     return w;
  71. }
  72.  
  73.  
  74.  
  75. void pw(winding_t *w)
  76. {
  77.     int        i;
  78.     for (i=0 ; i<w->numpoints ; i++)
  79.         printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
  80. }
  81.  
  82. void prl(leaf_t *l)
  83. {
  84.     int            i;
  85.     portal_t    *p;
  86.     plane_t        pl;
  87.     
  88.     for (i=0 ; i<l->numportals ; i++)
  89.     {
  90.         p = l->portals[i];
  91.         pl = p->plane;
  92.         printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
  93.     }
  94. }
  95.  
  96.  
  97. //=============================================================================
  98.  
  99. /*
  100. =============
  101. SortPortals
  102.  
  103. Sorts the portals from the least complex, so the later ones can reuse
  104. the earlier information.
  105. =============
  106. */
  107. int PComp (const void *a, const void *b)
  108. {
  109.     if ( (*(portal_t **)a)->nummightsee == (*(portal_t **)b)->nummightsee)
  110.         return 0;
  111.     if ( (*(portal_t **)a)->nummightsee < (*(portal_t **)b)->nummightsee)
  112.         return -1;
  113.     return 1;
  114. }
  115. void SortPortals (void)
  116. {
  117.     int        i;
  118.     
  119.     for (i=0 ; i<numportals*2 ; i++)
  120.         sorted_portals[i] = &portals[i];
  121.  
  122.     if (nosort)
  123.         return;
  124.     qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
  125. }
  126.  
  127.  
  128. /*
  129. ==============
  130. LeafVectorFromPortalVector
  131. ==============
  132. */
  133. int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
  134. {
  135.     int            i;
  136.     portal_t    *p;
  137.     int            c_leafs;
  138.  
  139.  
  140.     memset (leafbits, 0, leafbytes);
  141.  
  142.     for (i=0 ; i<numportals*2 ; i++)
  143.     {
  144.         if (portalbits[i>>3] & (1<<(i&7)) )
  145.         {
  146.             p = portals+i;
  147.             leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
  148.         }
  149.     }
  150.  
  151.     c_leafs = CountBits (leafbits, portalclusters);
  152.  
  153.     return c_leafs;
  154. }
  155.  
  156.  
  157. /*
  158. ===============
  159. ClusterMerge
  160.  
  161. Merges the portal visibility for a leaf
  162. ===============
  163. */
  164. void ClusterMerge (int leafnum)
  165. {
  166.     leaf_t        *leaf;
  167.     byte        portalvector[MAX_PORTALS/8];
  168.     byte        uncompressed[MAX_MAP_LEAFS/8];
  169.     byte        compressed[MAX_MAP_LEAFS/8];
  170.     int            i, j;
  171.     int            numvis;
  172.     byte        *dest;
  173.     portal_t    *p;
  174.     int            pnum;
  175.  
  176.     // OR together all the portalvis bits
  177.  
  178.     memset (portalvector, 0, portalbytes);
  179.     leaf = &leafs[leafnum];
  180.     for (i=0 ; i<leaf->numportals ; i++)
  181.     {
  182.         p = leaf->portals[i];
  183.         if (p->status != stat_done)
  184.             Error ("portal not done");
  185.         for (j=0 ; j<portallongs ; j++)
  186.             ((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
  187.         pnum = p - portals;
  188.         portalvector[pnum>>3] |= 1<<(pnum&7);
  189.     }
  190.  
  191.     // convert portal bits to leaf bits
  192.     numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
  193.  
  194.     if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
  195.         printf ("WARNING: Leaf portals saw into leaf\n");
  196.         
  197.     uncompressed[leafnum>>3] |= (1<<(leafnum&7));
  198.     numvis++;        // count the leaf itself
  199.  
  200.     // save uncompressed for PHS calculation
  201.     memcpy (uncompressedvis + leafnum*leafbytes, uncompressed, leafbytes);
  202.  
  203. //
  204. // compress the bit string
  205. //
  206.     qprintf ("cluster %4i : %4i visible\n", leafnum, numvis);
  207.     totalvis += numvis;
  208.  
  209.     i = CompressVis (uncompressed, compressed);
  210.  
  211.     dest = vismap_p;
  212.     vismap_p += i;
  213.     
  214.     if (vismap_p > vismap_end)
  215.         Error ("Vismap expansion overflow");
  216.  
  217.     dvis->bitofs[leafnum][DVIS_PVS] = dest-vismap;
  218.  
  219.     memcpy (dest, compressed, i);    
  220. }
  221.  
  222.  
  223. /*
  224. ==================
  225. CalcPortalVis
  226. ==================
  227. */
  228. void CalcPortalVis (void)
  229. {
  230.     int        i;
  231.  
  232. // fastvis just uses mightsee for a very loose bound
  233.     if (fastvis)
  234.     {
  235.         for (i=0 ; i<numportals*2 ; i++)
  236.         {
  237.             portals[i].portalvis = portals[i].portalflood;
  238.             portals[i].status = stat_done;
  239.         }
  240.         return;
  241.     }
  242.     
  243.     RunThreadsOnIndividual (numportals*2, true, PortalFlow);
  244.  
  245. }
  246.  
  247.  
  248. /*
  249. ==================
  250. CalcVis
  251. ==================
  252. */
  253. void CalcVis (void)
  254. {
  255.     int        i;
  256.  
  257.     RunThreadsOnIndividual (numportals*2, true, BasePortalVis);
  258.  
  259. //    RunThreadsOnIndividual (numportals*2, true, BetterPortalVis);
  260.  
  261.     SortPortals ();
  262.     
  263.     CalcPortalVis ();
  264.  
  265. //
  266. // assemble the leaf vis lists by oring and compressing the portal lists
  267. //
  268.     for (i=0 ; i<portalclusters ; i++)
  269.         ClusterMerge (i);
  270.         
  271.     printf ("Average clusters visible: %i\n", totalvis / portalclusters);
  272. }
  273.  
  274.  
  275. void SetPortalSphere (portal_t *p)
  276. {
  277.     int        i;
  278.     vec3_t    total, dist;
  279.     winding_t    *w;
  280.     float    r, bestr;
  281.  
  282.     w = p->winding;
  283.     VectorCopy (vec3_origin, total);
  284.     for (i=0 ; i<w->numpoints ; i++)
  285.     {
  286.         VectorAdd (total, w->points[i], total);
  287.     }
  288.     
  289.     for (i=0 ; i<3 ; i++)
  290.         total[i] /= w->numpoints;
  291.  
  292.     bestr = 0;        
  293.     for (i=0 ; i<w->numpoints ; i++)
  294.     {
  295.         VectorSubtract (w->points[i], total, dist);
  296.         r = VectorLength (dist);
  297.         if (r > bestr)
  298.             bestr = r;
  299.     }
  300.     VectorCopy (total, p->origin);
  301.     p->radius = bestr;
  302. }
  303.  
  304. /*
  305. ============
  306. LoadPortals
  307. ============
  308. */
  309. void LoadPortals (char *name)
  310. {
  311.     int            i, j;
  312.     portal_t    *p;
  313.     leaf_t        *l;
  314.     char        magic[80];
  315.     FILE        *f;
  316.     int            numpoints;
  317.     winding_t    *w;
  318.     int            leafnums[2];
  319.     plane_t        plane;
  320.     
  321.     if (!strcmp(name,"-"))
  322.         f = stdin;
  323.     else
  324.     {
  325.         f = fopen(name, "r");
  326.         if (!f)
  327.             Error ("LoadPortals: couldn't read %s\n",name);
  328.     }
  329.  
  330.     if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalclusters, &numportals) != 3)
  331.         Error ("LoadPortals: failed to read header");
  332.     if (strcmp(magic,PORTALFILE))
  333.         Error ("LoadPortals: not a portal file");
  334.  
  335.     printf ("%4i portalclusters\n", portalclusters);
  336.     printf ("%4i numportals\n", numportals);
  337.  
  338.     // these counts should take advantage of 64 bit systems automatically
  339.     leafbytes = ((portalclusters+63)&~63)>>3;
  340.     leaflongs = leafbytes/sizeof(long);
  341.     
  342.     portalbytes = ((numportals*2+63)&~63)>>3;
  343.     portallongs = portalbytes/sizeof(long);
  344.  
  345. // each file portal is split into two memory portals
  346.     portals = malloc(2*numportals*sizeof(portal_t));
  347.     memset (portals, 0, 2*numportals*sizeof(portal_t));
  348.     
  349.     leafs = malloc(portalclusters*sizeof(leaf_t));
  350.     memset (leafs, 0, portalclusters*sizeof(leaf_t));
  351.  
  352.     originalvismapsize = portalclusters*leafbytes;
  353.     uncompressedvis = malloc(originalvismapsize);
  354.  
  355.     vismap = vismap_p = dvisdata;
  356.     dvis->numclusters = portalclusters;
  357.     vismap_p = (byte *)&dvis->bitofs[portalclusters];
  358.  
  359.     vismap_end = vismap + MAX_MAP_VISIBILITY;
  360.         
  361.     for (i=0, p=portals ; i<numportals ; i++)
  362.     {
  363.         if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
  364.             != 3)
  365.             Error ("LoadPortals: reading portal %i", i);
  366.         if (numpoints > MAX_POINTS_ON_WINDING)
  367.             Error ("LoadPortals: portal %i has too many points", i);
  368.         if ( (unsigned)leafnums[0] > portalclusters
  369.         || (unsigned)leafnums[1] > portalclusters)
  370.             Error ("LoadPortals: reading portal %i", i);
  371.         
  372.         w = p->winding = NewWinding (numpoints);
  373.         w->original = true;
  374.         w->numpoints = numpoints;
  375.         
  376.         for (j=0 ; j<numpoints ; j++)
  377.         {
  378.             double    v[3];
  379.             int        k;
  380.  
  381.             // scanf into double, then assign to vec_t
  382.             // so we don't care what size vec_t is
  383.             if (fscanf (f, "(%lf %lf %lf ) "
  384.             , &v[0], &v[1], &v[2]) != 3)
  385.                 Error ("LoadPortals: reading portal %i", i);
  386.             for (k=0 ; k<3 ; k++)
  387.                 w->points[j][k] = v[k];
  388.         }
  389.         fscanf (f, "\n");
  390.         
  391.     // calc plane
  392.         PlaneFromWinding (w, &plane);
  393.  
  394.     // create forward portal
  395.         l = &leafs[leafnums[0]];
  396.         if (l->numportals == MAX_PORTALS_ON_LEAF)
  397.             Error ("Leaf with too many portals");
  398.         l->portals[l->numportals] = p;
  399.         l->numportals++;
  400.         
  401.         p->winding = w;
  402.         VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
  403.         p->plane.dist = -plane.dist;
  404.         p->leaf = leafnums[1];
  405.         SetPortalSphere (p);
  406.         p++;
  407.         
  408.     // create backwards portal
  409.         l = &leafs[leafnums[1]];
  410.         if (l->numportals == MAX_PORTALS_ON_LEAF)
  411.             Error ("Leaf with too many portals");
  412.         l->portals[l->numportals] = p;
  413.         l->numportals++;
  414.         
  415.         p->winding = NewWinding(w->numpoints);
  416.         p->winding->numpoints = w->numpoints;
  417.         for (j=0 ; j<w->numpoints ; j++)
  418.         {
  419.             VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
  420.         }
  421.  
  422.         p->plane = plane;
  423.         p->leaf = leafnums[0];
  424.         SetPortalSphere (p);
  425.         p++;
  426.  
  427.     }
  428.     
  429.     fclose (f);
  430. }
  431.  
  432.  
  433. /*
  434. ================
  435. CalcPHS
  436.  
  437. Calculate the PHS (Potentially Hearable Set)
  438. by ORing together all the PVS visible from a leaf
  439. ================
  440. */
  441. void CalcPHS (void)
  442. {
  443.     int        i, j, k, l, index;
  444.     int        bitbyte;
  445.     long    *dest, *src;
  446.     byte    *scan;
  447.     int        count;
  448.     byte    uncompressed[MAX_MAP_LEAFS/8];
  449.     byte    compressed[MAX_MAP_LEAFS/8];
  450.  
  451.     printf ("Building PHS...\n");
  452.  
  453.     count = 0;
  454.     for (i=0 ; i<portalclusters ; i++)
  455.     {
  456.         scan = uncompressedvis + i*leafbytes;
  457.         memcpy (uncompressed, scan, leafbytes);
  458.         for (j=0 ; j<leafbytes ; j++)
  459.         {
  460.             bitbyte = scan[j];
  461.             if (!bitbyte)
  462.                 continue;
  463.             for (k=0 ; k<8 ; k++)
  464.             {
  465.                 if (! (bitbyte & (1<<k)) )
  466.                     continue;
  467.                 // OR this pvs row into the phs
  468.                 index = ((j<<3)+k);
  469.                 if (index >= portalclusters)
  470.                     Error ("Bad bit in PVS");    // pad bits should be 0
  471.                 src = (long *)(uncompressedvis + index*leafbytes);
  472.                 dest = (long *)uncompressed;
  473.                 for (l=0 ; l<leaflongs ; l++)
  474.                     ((long *)uncompressed)[l] |= src[l];
  475.             }
  476.         }
  477.         for (j=0 ; j<portalclusters ; j++)
  478.             if (uncompressed[j>>3] & (1<<(j&7)) )
  479.                 count++;
  480.  
  481.     //
  482.     // compress the bit string
  483.     //
  484.         j = CompressVis (uncompressed, compressed);
  485.  
  486.         dest = (long *)vismap_p;
  487.         vismap_p += j;
  488.         
  489.         if (vismap_p > vismap_end)
  490.             Error ("Vismap expansion overflow");
  491.  
  492.         dvis->bitofs[i][DVIS_PHS] = (byte *)dest-vismap;
  493.  
  494.         memcpy (dest, compressed, j);    
  495.     }
  496.  
  497.     printf ("Average clusters hearable: %i\n", count/portalclusters);
  498. }
  499.  
  500. /*
  501. ===========
  502. main
  503. ===========
  504. */
  505. int main (int argc, char **argv)
  506. {
  507.     char    portalfile[1024];
  508.     char        source[1024];
  509.     char        name[1024];
  510.     int        i;
  511.     double        start, end;
  512.         
  513.     printf ("---- vis ----\n");
  514.  
  515.     verbose = false;
  516.     for (i=1 ; i<argc ; i++)
  517.     {
  518.         if (!strcmp(argv[i],"-threads"))
  519.         {
  520.             numthreads = atoi (argv[i+1]);
  521.             i++;
  522.         }
  523.         else if (!strcmp(argv[i], "-fast"))
  524.         {
  525.             printf ("fastvis = true\n");
  526.             fastvis = true;
  527.         }
  528.         else if (!strcmp(argv[i], "-level"))
  529.         {
  530.             testlevel = atoi(argv[i+1]);
  531.             printf ("testlevel = %i\n", testlevel);
  532.             i++;
  533.         }
  534.         else if (!strcmp(argv[i], "-v"))
  535.         {
  536.             printf ("verbose = true\n");
  537.             verbose = true;
  538.         }
  539.         else if (!strcmp (argv[i],"-nosort"))
  540.         {
  541.             printf ("nosort = true\n");
  542.             nosort = true;
  543.         }
  544.         else if (!strcmp (argv[i],"-tmpin"))
  545.             strcpy (inbase, "/tmp");
  546.         else if (!strcmp (argv[i],"-tmpout"))
  547.             strcpy (outbase, "/tmp");
  548.         else if (argv[i][0] == '-')
  549.             Error ("Unknown option \"%s\"", argv[i]);
  550.         else
  551.             break;
  552.     }
  553.  
  554.     if (i != argc - 1)
  555.         Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
  556.  
  557.     start = I_FloatTime ();
  558.     
  559.     ThreadSetDefault ();
  560.  
  561.     SetQdirFromPath (argv[i]);    
  562.     strcpy (source, ExpandArg(argv[i]));
  563.     StripExtension (source);
  564.     DefaultExtension (source, ".bsp");
  565.  
  566.     sprintf (name, "%s%s", inbase, source);
  567.     printf ("reading %s\n", name);
  568.     LoadBSPFile (name);
  569.     if (numnodes == 0 || numfaces == 0)
  570.         Error ("Empty map");
  571.  
  572.     sprintf (portalfile, "%s%s", inbase, ExpandArg(argv[i]));
  573.     StripExtension (portalfile);
  574.     strcat (portalfile, ".prt");
  575.     
  576.     printf ("reading %s\n", portalfile);
  577.     LoadPortals (portalfile);
  578.     
  579.     CalcVis ();
  580.  
  581.     CalcPHS ();
  582.  
  583.     visdatasize = vismap_p - dvisdata;    
  584.     printf ("visdatasize:%i  compressed from %i\n", visdatasize, originalvismapsize*2);
  585.  
  586.     sprintf (name, "%s%s", outbase, source);
  587.     printf ("writing %s\n", name);
  588.     WriteBSPFile (name);    
  589.     
  590.     end = I_FloatTime ();
  591.     printf ("%5.1f seconds elapsed\n", end-start);
  592.  
  593.     return 0;
  594. }
  595.  
  596.